package com.zeyu.framework.tools.schedule.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.quartz.Job;
import org.quartz.Trigger;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * quartz entity for web display <--> quartz job database.
 * Created by zeyuphoenix on 16/6/20.
 */
public class JobEntity implements Serializable {

    // ================================================================
    // Constants
    // ================================================================

    // 任务中的常量
    /**
     * 保存entity到运行中,保证运行中状态可以获取
     */
    public static final String ENTITY_KEY = "ENTITY_KEY";
    /**
     * 类型为任务
     */
    public static final int TYPE_JOB = 1;
    /**
     * 类型为任务组
     */
    public static final int TYPE_GROUP = 0;
    /**
     * 根节点
     */
    public static final String NODE_ROOT_NAME = "所有任务";

    // 任务树常量
    /**
     * 树的根节点
     */
    public static final String NODE_ROOT = "root";
    /**
     * 树的节点Id、pid、name、type、icon、selected、expanded、子节点
     */
    public static final String ATTR_ID = "id";
    public static final String ATTR_PID = "pId";
    public static final String ATTR_NAME = "name";
    public static final String ATTR_TYPE = "type";

    // 默认的任务组
    /** 监控管理组 */
    public static final String GROUP_MONITOR_MANAGER = "监控管理";
    /** 数据库管理组 */
    public static final String GROUP_DATABASE_MANAGER = "数据库管理";
    /** 报表管理组 */
    public static final String GROUP_REPORT_MANAGER = "报表管理";
    /** 其它管理组 */
    public static final String GROUP_OTHER_MANAGER = "其它管理";

    // 默认的任务
    /** 监控管理组 */
    /** 服务器自监控任务 */
    public static final String JOB_SERVER_MONITOR = "Server自监控";
    /** web服务器自监控任务 */
    public static final String JOB_WEB_SERVER_MONITOR = "Web服务器监控";
    /** 设备指标采集任务 */
    public static final String JOB_DEVICE_COLLECT_MONITOR = "设备指标采集";
    /** 数据库监控任务-mysql*/
    public static final String JOB_DATABASE_MYSQL_MONITOR = "MySQL数据库监控";
    /** 数据库监控任务 -mongodb*/
    public static final String JOB_DATABASE_MONGODB_MONITOR = "MongoDB数据库监控";
    /** 数据库监控任务 -redis*/
    public static final String JOB_DATABASE_REDIS_MONITOR = "Redis数据库监控";

    /** 数据库管理组 */
    /** 数据库备份任务 */
    public static final String JOB_DATABASE_BACKUP = "数据库备份";
    /** 数据库清理任务 */
    public static final String JOB_DATABASE_CLEAN = "数据库清理";

    /** 报表管理组 */
    /** 日报表邮件推送任务 */
    public static final String JOB_REPORT_MAIL_PUSH_DAY = "日报表邮件推送";
    /** 周报表邮件推送任务 */
    public static final String JOB_REPORT_MAIL_PUSH_WEEK = "周报表邮件推送";
    /** 月报表邮件推送任务 */
    public static final String JOB_REPORT_MAIL_PUSH_MONTH = "月报表邮件推送";
    /** 报表定期归档任务 */
    public static final String JOB_REPORT_MERGE = "报表定期归档";

    /**其他管理组*/
    /** 缓存图片清理任务 */
    public static final String JOB_CLEAN_CACHE = "缓存图片清理";

    // ================================================================
    // Fields
    // ================================================================

    // 主键,为了页面而设置,默认是 任务名称+任务分组
    private String id;

    // 任务名称
    private String name;
    // 任务分组
    private String group;
    // 任务类型
    private int type;
    // 任务描述
    private String description;
    // 持久化
    private boolean persistJobDataAfterExecution = true;

    // 任务执行时调用哪个实现类
    private Class<? extends Job> jobClass;

    // 任务开始时间,不设置即为立即开始
    private Date startDate;
    // 任务结束时间,不设置则为永不结束
    private Date endDate;

    // 任务周期设置: 间隔和cron方式二选一
    // 任务间隔周期
    private int interval;
    // 任务间隔周期单位,最小到秒
    private TimeUnit unit;
    // json使用
    private int unitType;
    // 任务调度表达式,如果存在,则interval和unit无效
    private String cron;

    // 是否记录历史记录
    private boolean history = false;

    // 传递一些用户自定义数据,任务执行中可以使用
    private Map<String, Object> datas = new HashMap<>();

    // 任务运行期的一些状态,新创建时全为默认值
    private JobRuntimeEntity jobRuntimeEntity = new JobRuntimeEntity();

    // ================================================================
    // Constructors
    // ================================================================

    public JobEntity() {
    }

    public JobEntity(String name, String group) {
        this.name = name;
        this.group = group;
    }

    public JobEntity(String name, String group, Class<? extends Job> jobClass, Date startDate, Date endDate,
                     int interval, TimeUnit unit) {
        this.name = name;
        this.group = group;
        this.jobClass = jobClass;
        this.startDate = startDate;
        this.endDate = endDate;
        this.interval = interval;
        this.unit = unit;
    }

    public JobEntity(String name, String group, Class<? extends Job> jobClass, Date startDate, Date endDate,
                     String cron) {
        this.name = name;
        this.group = group;
        this.jobClass = jobClass;
        this.startDate = startDate;
        this.endDate = endDate;
        this.cron = cron;
    }

    public JobEntity(String name, String group, String description, Class<? extends Job> jobClass, Date startDate,
                     Date endDate, int interval, TimeUnit unit, String cron, Map<String, Object> datas) {
        this.name = name;
        this.group = group;
        this.description = description;
        this.jobClass = jobClass;
        this.startDate = startDate;
        this.endDate = endDate;
        this.interval = interval;
        this.unit = unit;
        this.cron = cron;
        this.datas = datas;
    }

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    @Override
    public String toString() {
        return "JobEntity{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", group='" + group + '\'' +
                ", type=" + type +
                ", description='" + description + '\'' +
                ", persistJobDataAfterExecution=" + persistJobDataAfterExecution +
                ", jobClass=" + jobClass +
                ", startDate=" + startDate +
                ", endDate=" + endDate +
                ", interval=" + interval +
                ", unit=" + unit +
                ", cron='" + cron + '\'' +
                ", datas=" + datas +
                ", jobRuntimeEntity=" + jobRuntimeEntity +
                '}';
    }

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    // ================================================================
    // Getter & Setter
    // ================================================================

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGroup() {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean isPersistJobDataAfterExecution() {
        return persistJobDataAfterExecution;
    }

    public void setPersistJobDataAfterExecution(boolean persistJobDataAfterExecution) {
        this.persistJobDataAfterExecution = persistJobDataAfterExecution;
    }

    public Class<? extends Job> getJobClass() {
        return jobClass;
    }

    public void setJobClass(Class<? extends Job> jobClass) {
        this.jobClass = jobClass;
    }

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

    public int getInterval() {
        return interval;
    }

    public void setInterval(int interval) {
        this.interval = interval;
    }

    @JsonIgnore
    public TimeUnit getUnit() {
        return unit;
    }

    public void setUnit(TimeUnit unit) {
        this.unit = unit;
    }

    public int getUnitType() {
        if (this.unit != null && this.unitType > 0) {
            if (unit == TimeUnit.DAYS) {
                return 4;
            } else if (unit == TimeUnit.HOURS) {
                return 3;
            } else if (unit == TimeUnit.MINUTES) {
                return 2;
            }
        }
        return 1;
    }

    public void setUnitType(int unitType) {
        this.unitType = unitType;
        if (unitType == 2) {
            this.unit = TimeUnit.DAYS;
        } else if (unitType == 3) {
            this.unit = TimeUnit.HOURS;
        } else if (unitType == 4) {
            this.unit = TimeUnit.MINUTES;
        } else {
            this.unit = TimeUnit.SECONDS;
        }
    }

    public String getCron() {
        return cron;
    }

    public void setCron(String cron) {
        this.cron = cron;
    }

    public boolean isHistory() {
        return history;
    }

    public void setHistory(boolean history) {
        this.history = history;
    }

    public Map<String, Object> getDatas() {
        return datas;
    }

    public void setDatas(Map<String, Object> datas) {
        this.datas = datas;
    }

    public JobRuntimeEntity getJobRuntimeEntity() {
        return jobRuntimeEntity;
    }

    public void setJobRuntimeEntity(JobRuntimeEntity jobRuntimeEntity) {
        this.jobRuntimeEntity = jobRuntimeEntity;
    }

    // ================================================================
    // Private Methods
    // ================================================================

    /**
     * 任务的实时信息,根据运行态获取,页面展示用
     */
    public static class JobRuntimeEntity implements Serializable {

        // ================================================================
        // Fields
        // ================================================================

        // 执行时间
        private Date fireTime = new Date();
        // 计划执行时间
        private Date scheduledFireTime = new Date();
        // 下一次执行时间
        private Date nextFireTime = new Date();
        // 上一次执行时间
        private Date previousFireTime = new Date();
        // 执行次数
        private int fireCount = 0;
        // 任务状态
        /**
         * 任务状态-无
         * STATUS_NONE = 0
         * 任务状态-正常
         * STATUS_NORMAL = 1
         * 任务状态-暂停
         * STATUS_PAUSED = 2
         * 任务状态-完成
         * STATUS_COMPLETE = 3
         * 任务状态-错误
         * STATUS_ERROR = 4
         * 任务状态-锁定
         * STATUS_BLOCKED = 5
         */
        private int status = Trigger.TriggerState.NONE.ordinal();

        // ================================================================
        // Methods from/for super Interfaces or SuperClass
        // ================================================================

        @Override
        public String toString() {
            return "JobRuntimeEntity{" +
                    "fireTime=" + fireTime +
                    ", scheduledFireTime=" + scheduledFireTime +
                    ", nextFireTime=" + nextFireTime +
                    ", previousFireTime=" + previousFireTime +
                    ", fireCount=" + fireCount +
                    ", statue=" + status +
                    '}';
        }

        // ================================================================
        // Getter & Setter
        // ================================================================

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        public Date getFireTime() {
            return fireTime;
        }

        public void setFireTime(Date fireTime) {
            this.fireTime = fireTime;
        }

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        public Date getScheduledFireTime() {
            return scheduledFireTime;
        }

        public void setScheduledFireTime(Date scheduledFireTime) {
            this.scheduledFireTime = scheduledFireTime;
        }

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        public Date getNextFireTime() {
            return nextFireTime;
        }

        public void setNextFireTime(Date nextFireTime) {
            this.nextFireTime = nextFireTime;
        }

        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        public Date getPreviousFireTime() {
            return previousFireTime;
        }

        public void setPreviousFireTime(Date previousFireTime) {
            this.previousFireTime = previousFireTime;
        }

        public int getFireCount() {
            return fireCount;
        }

        public void setFireCount(int fireCount) {
            this.fireCount = fireCount;
        }

        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }
    }

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================

}
